package metadata

import (
	"encoding/json"
	"fmt"
	"os"
	"path/filepath"
	"strings"
	"sync"
	"time"
)

// DefaultManager 默认元数据管理器实现
type DefaultManager struct {
	extractor MetadataExtractor
	storage   MetadataStorage
	config    *ExtractorConfig
	mutex     sync.RWMutex
}

// NewDefaultManager 创建默认元数据管理器
func NewDefaultManager(storagePath string) *DefaultManager {
	config := DefaultExtractorConfig()

	return &DefaultManager{
		extractor: NewBaseExtractor(config),
		storage:   NewFileStorage(storagePath),
		config:    config,
	}
}

// ProcessFile 处理单个文件
func (m *DefaultManager) ProcessFile(filePath string) (*DocumentMetadata, error) {
	m.mutex.Lock()
	defer m.mutex.Unlock()

	// 检查文件是否存在
	if _, err := os.Stat(filePath); os.IsNotExist(err) {
		return nil, fmt.Errorf("文件不存在: %s", filePath)
	}

	// 读取文件内容
	content, err := os.ReadFile(filePath)
	if err != nil {
		return nil, fmt.Errorf("读取文件失败: %v", err)
	}

	// 提取元数据
	metadata, err := m.extractor.Extract(string(content), filePath, m.config)
	if err != nil {
		return nil, fmt.Errorf("元数据提取失败: %v", err)
	}

	// 验证元数据
	if err := m.extractor.ValidateMetadata(metadata); err != nil {
		return nil, fmt.Errorf("元数据验证失败: %v", err)
	}

	// 存储元数据
	if err := m.storage.Store(filePath, metadata); err != nil {
		return nil, fmt.Errorf("元数据存储失败: %v", err)
	}

	return metadata, nil
}

// ProcessDirectory 处理目录
func (m *DefaultManager) ProcessDirectory(dirPath string, recursive bool) (map[string]*DocumentMetadata, error) {
	results := make(map[string]*DocumentMetadata)
	var errors []string

	err := filepath.Walk(dirPath, func(path string, info os.FileInfo, err error) error {
		if err != nil {
			errors = append(errors, fmt.Sprintf("访问路径失败 %s: %v", path, err))
			return nil
		}

		// 跳过目录
		if info.IsDir() {
			if !recursive && path != dirPath {
				return filepath.SkipDir
			}
			return nil
		}

		// 检查是否为支持的文件类型
		if !m.isSupportedFile(path) {
			return nil
		}

		// 处理文件
		metadata, err := m.ProcessFile(path)
		if err != nil {
			errors = append(errors, fmt.Sprintf("处理文件失败 %s: %v", path, err))
			return nil
		}

		results[path] = metadata
		return nil
	})

	if err != nil {
		return nil, fmt.Errorf("目录遍历失败: %v", err)
	}

	// 如果有错误，记录但不中断处理
	if len(errors) > 0 {
		fmt.Printf("处理过程中出现 %d 个错误:\n", len(errors))
		for _, errMsg := range errors {
			fmt.Printf("- %s\n", errMsg)
		}
	}

	return results, nil
}

// UpdateMetadata 更新元数据
func (m *DefaultManager) UpdateMetadata(filePath string, force bool) (*DocumentMetadata, error) {
	m.mutex.Lock()
	defer m.mutex.Unlock()

	// 检查是否需要更新
	if !force {
		existing, err := m.storage.Retrieve(filePath)
		if err == nil && existing != nil {
			// 检查文件修改时间
			fileInfo, err := os.Stat(filePath)
			if err == nil && fileInfo.ModTime().Before(existing.ExtractedAt) {
				return existing, nil // 文件未修改，无需更新
			}
		}
	}

	// 重新处理文件
	return m.ProcessFile(filePath)
}

// GetMetadata 获取元数据
func (m *DefaultManager) GetMetadata(filePath string) (*DocumentMetadata, error) {
	m.mutex.RLock()
	defer m.mutex.RUnlock()

	return m.storage.Retrieve(filePath)
}

// SearchByMetadata 根据元数据搜索
func (m *DefaultManager) SearchByMetadata(criteria map[string]interface{}) (map[string]*DocumentMetadata, error) {
	m.mutex.RLock()
	defer m.mutex.RUnlock()

	// 获取所有元数据
	allMetadata, err := m.storage.List()
	if err != nil {
		return nil, err
	}

	results := make(map[string]*DocumentMetadata)

	// 过滤匹配的元数据
	for filePath, metadata := range allMetadata {
		if m.matchesCriteria(metadata, criteria) {
			results[filePath] = metadata
		}
	}

	return results, nil
}

// GetStatistics 获取统计信息
func (m *DefaultManager) GetStatistics() (map[string]interface{}, error) {
	m.mutex.RLock()
	defer m.mutex.RUnlock()

	allMetadata, err := m.storage.List()
	if err != nil {
		return nil, err
	}

	stats := make(map[string]interface{})

	totalFiles := len(allMetadata)
	totalWords := 0
	totalLines := 0
	categories := make(map[string]int)
	languages := make(map[string]int)
	authors := make(map[string]int)

	var totalQuality float64
	var totalConfidence float64

	for _, metadata := range allMetadata {
		totalWords += metadata.WordCount
		totalLines += metadata.LineCount
		totalQuality += metadata.Quality
		totalConfidence += metadata.Confidence

		if metadata.Category != "" {
			categories[metadata.Category]++
		}

		if metadata.Language != "" {
			languages[metadata.Language]++
		}

		if metadata.Author != "" {
			authors[metadata.Author]++
		}
	}

	stats["total_files"] = totalFiles
	stats["total_words"] = totalWords
	stats["total_lines"] = totalLines
	stats["categories"] = categories
	stats["languages"] = languages
	stats["authors"] = authors

	if totalFiles > 0 {
		stats["average_quality"] = totalQuality / float64(totalFiles)
		stats["average_confidence"] = totalConfidence / float64(totalFiles)
		stats["average_words_per_file"] = float64(totalWords) / float64(totalFiles)
		stats["average_lines_per_file"] = float64(totalLines) / float64(totalFiles)
	}

	return stats, nil
}

// SetConfig 设置配置
func (m *DefaultManager) SetConfig(config *ExtractorConfig) {
	m.mutex.Lock()
	defer m.mutex.Unlock()

	if config != nil {
		m.config = config
		m.extractor = NewBaseExtractor(config)
	}
}

// GetConfig 获取配置
func (m *DefaultManager) GetConfig() *ExtractorConfig {
	m.mutex.RLock()
	defer m.mutex.RUnlock()

	return m.config
}

// 私有辅助方法

// isSupportedFile 检查是否为支持的文件类型
func (m *DefaultManager) isSupportedFile(filePath string) bool {
	ext := strings.ToLower(filepath.Ext(filePath))
	supportedExts := []string{".md", ".txt", ".doc", ".docx"}

	for _, supportedExt := range supportedExts {
		if ext == supportedExt {
			return true
		}
	}

	return false
}

// matchesCriteria 检查元数据是否匹配搜索条件
func (m *DefaultManager) matchesCriteria(metadata *DocumentMetadata, criteria map[string]interface{}) bool {
	for key, value := range criteria {
		switch key {
		case "title":
			if !strings.Contains(strings.ToLower(metadata.Title), strings.ToLower(value.(string))) {
				return false
			}
		case "author":
			if !strings.Contains(strings.ToLower(metadata.Author), strings.ToLower(value.(string))) {
				return false
			}
		case "category":
			if metadata.Category != value.(string) {
				return false
			}
		case "language":
			if metadata.Language != value.(string) {
				return false
			}
		case "keywords":
			searchKeywords := value.([]string)
			found := false
			for _, searchKeyword := range searchKeywords {
				for _, keyword := range metadata.Keywords {
					if strings.Contains(strings.ToLower(keyword), strings.ToLower(searchKeyword)) {
						found = true
						break
					}
				}
				if found {
					break
				}
			}
			if !found {
				return false
			}
		case "min_quality":
			if metadata.Quality < value.(float64) {
				return false
			}
		case "min_confidence":
			if metadata.Confidence < value.(float64) {
				return false
			}
		case "min_words":
			if metadata.WordCount < value.(int) {
				return false
			}
		case "created_after":
			if metadata.CreatedAt.Before(value.(time.Time)) {
				return false
			}
		case "created_before":
			if metadata.CreatedAt.After(value.(time.Time)) {
				return false
			}
		}
	}

	return true
}

// FileStorage 基于文件的元数据存储实现
type FileStorage struct {
	basePath string
	mutex    sync.RWMutex
}

// NewFileStorage 创建文件存储
func NewFileStorage(basePath string) *FileStorage {
	// 确保目录存在
	os.MkdirAll(basePath, 0755)

	return &FileStorage{
		basePath: basePath,
	}
}

// Store 存储元数据
func (fs *FileStorage) Store(filePath string, metadata *DocumentMetadata) error {
	fs.mutex.Lock()
	defer fs.mutex.Unlock()

	// 生成存储路径
	storagePath := fs.getStoragePath(filePath)

	// 确保目录存在
	dir := filepath.Dir(storagePath)
	if err := os.MkdirAll(dir, 0755); err != nil {
		return fmt.Errorf("创建目录失败: %v", err)
	}

	// 序列化元数据
	data, err := json.MarshalIndent(metadata, "", "  ")
	if err != nil {
		return fmt.Errorf("序列化元数据失败: %v", err)
	}

	// 写入文件
	if err := os.WriteFile(storagePath, data, 0644); err != nil {
		return fmt.Errorf("写入元数据文件失败: %v", err)
	}

	return nil
}

// Retrieve 检索元数据
func (fs *FileStorage) Retrieve(filePath string) (*DocumentMetadata, error) {
	fs.mutex.RLock()
	defer fs.mutex.RUnlock()

	storagePath := fs.getStoragePath(filePath)

	// 检查文件是否存在
	if _, err := os.Stat(storagePath); os.IsNotExist(err) {
		return nil, fmt.Errorf("元数据文件不存在")
	}

	// 读取文件
	data, err := os.ReadFile(storagePath)
	if err != nil {
		return nil, fmt.Errorf("读取元数据文件失败: %v", err)
	}

	// 反序列化
	var metadata DocumentMetadata
	if err := json.Unmarshal(data, &metadata); err != nil {
		return nil, fmt.Errorf("反序列化元数据失败: %v", err)
	}

	return &metadata, nil
}

// Update 更新元数据
func (fs *FileStorage) Update(filePath string, metadata *DocumentMetadata) error {
	return fs.Store(filePath, metadata)
}

// Delete 删除元数据
func (fs *FileStorage) Delete(filePath string) error {
	fs.mutex.Lock()
	defer fs.mutex.Unlock()

	storagePath := fs.getStoragePath(filePath)

	if err := os.Remove(storagePath); err != nil && !os.IsNotExist(err) {
		return fmt.Errorf("删除元数据文件失败: %v", err)
	}

	return nil
}

// List 列出所有元数据
func (fs *FileStorage) List() (map[string]*DocumentMetadata, error) {
	fs.mutex.RLock()
	defer fs.mutex.RUnlock()

	results := make(map[string]*DocumentMetadata)

	err := filepath.Walk(fs.basePath, func(path string, info os.FileInfo, err error) error {
		if err != nil {
			return err
		}

		if info.IsDir() || !strings.HasSuffix(path, ".json") {
			return nil
		}

		// 读取元数据文件
		data, err := os.ReadFile(path)
		if err != nil {
			return nil // 跳过错误文件
		}

		var metadata DocumentMetadata
		if err := json.Unmarshal(data, &metadata); err != nil {
			return nil // 跳过错误文件
		}

		// 从存储路径反推原文件路径
		originalPath := fs.getOriginalPath(path)
		results[originalPath] = &metadata

		return nil
	})

	if err != nil {
		return nil, fmt.Errorf("遍历元数据目录失败: %v", err)
	}

	return results, nil
}

// Search 搜索元数据
func (fs *FileStorage) Search(query string) (map[string]*DocumentMetadata, error) {
	allMetadata, err := fs.List()
	if err != nil {
		return nil, err
	}

	results := make(map[string]*DocumentMetadata)
	query = strings.ToLower(query)

	for filePath, metadata := range allMetadata {
		// 在标题、摘要、关键词中搜索
		if strings.Contains(strings.ToLower(metadata.Title), query) ||
			strings.Contains(strings.ToLower(metadata.Summary), query) ||
			strings.Contains(strings.ToLower(metadata.Author), query) {
			results[filePath] = metadata
			continue
		}

		// 在关键词中搜索
		for _, keyword := range metadata.Keywords {
			if strings.Contains(strings.ToLower(keyword), query) {
				results[filePath] = metadata
				break
			}
		}
	}

	return results, nil
}

// getStoragePath 获取存储路径
func (fs *FileStorage) getStoragePath(filePath string) string {
	// 将文件路径转换为安全的存储路径
	safePath := strings.ReplaceAll(filePath, string(os.PathSeparator), "_")
	safePath = strings.ReplaceAll(safePath, ":", "_")
	return filepath.Join(fs.basePath, safePath+".json")
}

// getOriginalPath 从存储路径获取原始路径
func (fs *FileStorage) getOriginalPath(storagePath string) string {
	// 从存储路径反推原始路径
	filename := filepath.Base(storagePath)
	filename = strings.TrimSuffix(filename, ".json")
	originalPath := strings.ReplaceAll(filename, "_", string(os.PathSeparator))
	return originalPath
}

// 确保实现了接口
var _ MetadataManager = (*DefaultManager)(nil)
var _ MetadataStorage = (*FileStorage)(nil)
